#pragma once

#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<vector>
#include<semaphore.h>
#include<ctime>

using namespace std;


const int defaultcap = 5;

template<class T>
class RingQueue
{
private:
void P(sem_t &sem)
{
    sem_wait(&sem);
}

void V(sem_t &sem)
{
    sem_post(&sem);
}

void Lock(pthread_mutex_t &mutex)
{
    pthread_mutex_lock(&mutex);
}

void Unlock(pthread_mutex_t &mutex)
{
    pthread_mutex_unlock(&mutex);
}

public:
    RingQueue(int cap = defaultcap)
    :_ringqueue(cap)
    ,_cap(cap)
    ,_cstep(0)
    ,_pstep(0)
    {
        sem_init(&_cdata_sem, 0, 0);
        sem_init(&_pspace_sem, 0, cap);//这里限制了信号量最大为cap

        pthread_mutex_init(&_cmutex, nullptr);
        pthread_mutex_init(&_cmutex, nullptr);
    }

    // ~RingQueue()
    // {}

    void Push(const T& in)//生产
    {
        P(_pspace_sem);
        Lock(_pmutex);
        _ringqueue[_pstep++] = in;
        _pstep %= _cap;
        Unlock(_pmutex);
        V(_cdata_sem);
    }

    void Pop(T *out)//消费
    {
        P(_cdata_sem);
        Lock(_cmutex);
        *out = _ringqueue[_cstep++];
        _cstep %= _cap;
        Unlock(_cmutex);
        V(_pspace_sem);


    }
    ~RingQueue()
    {
        sem_destroy(&_cdata_sem);
        sem_destroy(&_pspace_sem);

        pthread_mutex_destroy(&_cmutex);
        pthread_mutex_destroy(&_pmutex);
    }
private:
    vector<T> _ringqueue;
    int _cap;

    int _cstep;//消费者下标
    int _pstep;//生产者下标

    sem_t _cdata_sem;//消费者关心的数据资源
    sem_t _pspace_sem;//消费者关注的空间资源

    pthread_mutex_t _cmutex;
    pthread_mutex_t _pmutex;

};